package com.lyrcsoft.rxjava1x.operators.convert;

import lombok.extern.slf4j.Slf4j;
import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;

import java.util.ArrayList;
import java.util.List;

/**
 * @author fujc2dev@126.com
 * @date 2024-11-19
 */
@Slf4j
public class Rx1flatMap {
    public static void main(String[] args) {
        log.debug("----------- rxJavaFlatMap ---------");
        List<Student> students = new ArrayList<>();
        List<Source> sources = new ArrayList<>();
        sources.add(new Source(1, "化学", 80));
        sources.add(new Source(2, "物理", 79));
        sources.add(new Source(3, "生物", 78));
        students.add(new Student("小明1", 1, sources));
        students.add(new Student("小明2", 1, sources));
        // 上例是一个学生与分数的集合，
        Observable.from(students)
                .flatMap(new Func1<Student, Observable<Source>>() {
                    @Override
                    public Observable<Source> call(Student student) {
                        log.debug("Item: " + student.name);
                        // 返回的是一个序列，序列，序列
                        return Observable.from(student.mSources);
                    }
                })
                .subscribe(new Action1<Source>() {
                    @Override
                    public void call(Source source) {
                        log.debug("Item: " + source + " 执行调用 获取线程id:" + Thread.currentThread().getId());
                    }
                });

        /**
         *  分析：flatMap 和map都可以将入参转化为另一个对象；
         *
         *    Observable：处理是就是序列。
         *    区别在于：flatMap会返回一个Observable对象，而map返回的是就是我们项要的对象。
         *    猜想：Rx1 发布、订阅是核心 ，将序列里数据一个一个发射处理，我发布一个，你就只应该收到一个，这是核心。
         *    如果要想我发布一个，你收到的是多个，那肯定就需要发布多个。
         *    flatMap为什么可以实现发布一个，收到多个？是不是内部帮我们把一个转为多个的？
         *    我们跟踪代码。内部代码与map的处理逻辑就多一个 merge，merge的参数是map(func)，而merge内部调用了lift
         *    通过查阅资料：lift允许在不修改原有Observable代码的情况下，向其添加自定义的操作或行为。通过lift，
         *    你可以“提升”或“包装”一个Observable，从而在其原有的发射元素流的基础上，插入一些自定义的逻辑。
         *    执行流程其实还是先走map函数，发射一个元素之后，通过调用lift，返回一个Observable
         *    这里就可以看出，我们其实订阅的的flatMap返回出来的新的一个Observable。不知道理解的对不对。感觉好像是那么回事
         */
    }
}


// ------------------------ 测试使用的类 -----------------------------

class Student {
    public    String name;//学生名字
    public   int id;
    public   List<Source> mSources;//每个学生的所有课程

    public Student(String name, int id, List<Source> sources) {
        this.name = name;
        this.id = id;
        mSources = sources;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", mSources=" + mSources +
                '}';
    }
}

class Source {
   public int sourceId;//id
    public    String name;//课程名
    public  int score;//成绩

    public Source(int sourceId, String name, int score) {
        this.sourceId = sourceId;
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Source{" +
                "sourceId=" + sourceId +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
